#include <stdio.h>
#include <string.h>
#include "device.h"
#include "usart.h"

#ifndef DEVICE_LOGGER_SERIAL
#define DEVICE_LOGGER_SERIAL        (0)
#endif
#ifndef DEVICE_LOGGER_LEVEL
#define DEVICE_LOGGER_LEVEL        (LOG__OFF)
#endif

DEFINE_LOGGER(DEV, 128, LOG__TRACE);

static void myputs(const char s[])
{
#if (DEVICE_LOGGER_SERIAL < 6) || (DEVICE_LOGGER_LEVEL > LOG__OFF)
    uart_send(DEVICE_LOGGER_SERIAL, (uint8_t *)s, strlen(s));
#endif
}
static void getmodule(char* s, int32_t maxlen)
{
    strcpy(s,"core");
}
static void gettime(char* s, int32_t maxlen)
{
    snprintf(s,maxlen+1,"%6d",system_get_tick());
}
static const LoggerConfig_ST dev_myLoggerConfig =
{
    myputs,NULL,gettime,getmodule,6,4,4,TRUE
};
static void _dev_logger_init(void)
{
#if (DEVICE_LOGGER_SERIAL < 6) || (DEVICE_LOGGER_LEVEL > LOG__OFF)
    uart_init(DEVICE_LOGGER_SERIAL,BAUD_RATE_115200,DATA_BITS_8,STOP_BITS_1,PARITY_NONE);
#endif
    Logger_Init(&dev_myLoggerConfig);
    Logger_SetGlobalLevel(DEVICE_LOGGER_LEVEL);
}

#define DEVICE_TABLE_SIZE       (32)
typedef struct
{
    char *dev_name;
    void *dev;
} dev_tb;
static dev_tb devt[DEVICE_TABLE_SIZE];
static uint8_t dev_count = 0;


extern unsigned char Image$$EARLY_INIT$$Base;
extern unsigned char Image$$EARLY_INIT$$Length;
static void module_init(void)
{
    struct command *cmd = (struct command *)&Image$$EARLY_INIT$$Base;
    int cnt = ((unsigned int)&Image$$EARLY_INIT$$Length) / sizeof(struct command);

    LogDebug("%s start\r\n",__FUNCTION__);
    LogInfo("total module : %d\r\n",cnt);

    for (int i = 0; i < cnt; i++)
    {
        cmd->func();
        cmd++;
    }
}

int dev_init(void)
{
    _dev_logger_init();
    LogDebug("%s start\r\n",__FUNCTION__);
    LogInfo("dev table size max : %d\r\n",DEVICE_TABLE_SIZE);
    memset(devt, 0x00, sizeof(dev_tb)*DEVICE_TABLE_SIZE);

    module_init();
    return 1;
}

int dev_register(char *dev_name, void *dev)
{
    if((dev_name == NULL)||(dev == NULL))
    {
        LogError("%s NULL error\r\n",__FUNCTION__);
        return -1;
    }
    if(dev_count >= DEVICE_TABLE_SIZE)
    {
        LogError("%s count error\r\n",__FUNCTION__);
        return -2;
    }
    if(dev_get(dev_name) != NULL)
    {
        LogError("%s name:%s error\r\n",__FUNCTION__,dev_name);
        return -3;
    }
    LogDebug("%s name:%s\r\n", __FUNCTION__, dev_name);
    devt[dev_count].dev_name = dev_name;
    devt[dev_count].dev = dev;
    dev_count++;

    return 1;
}

void *dev_get(char *dev_name)
{
    if(dev_name == NULL)
        return NULL;

    void *device = NULL;
    for(int i = 0; i < DEVICE_TABLE_SIZE; i++)
    {
        if((devt[i].dev_name == NULL)&&(devt[i].dev == NULL))
        {
            break;
        }
        if(strcmp(dev_name, devt[i].dev_name) == 0)
        {
            device = devt[i].dev;
            break;
        }
    }
    return device;
}
